/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package trab_sd;

import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;

/**
 *
 * @author moacirnq
 */
public class FileSender implements Runnable {
	private Socket connection;
	private File file;
	private ObjectOutputStream out;
	private ObjectInputStream in;
	private FileInputStream fin;
	private String fname;
	private long fsize;
	private UserID dst;
	private User localUser;
	private boolean cont;
	
	public static void copyFile(File src, File dst) throws Exception{
		
		if (dst.exists() && dst.length() == src.length()) {
			return;
		}
		
		dst.createNewFile();
		FileInputStream sin = new FileInputStream(src);
		FileOutputStream dout = new FileOutputStream(dst);
		
		byte [] buffer = new byte[ (int) src.length() ];
		sin.read(buffer);
		dout.write(buffer);
		dout.flush();
		dout.close();
		sin.close();
		
	}
	
	public FileSender ( User localUser, String fPath, String fName, UserID dst ) {
		try {
			cont = true;
			this.dst = dst;
			this.localUser = localUser;
			connection = new Socket( dst.getName(), dst.getPort() );
			connection.setSoTimeout(50000);
			file = new File(fPath + fName);
			if (!file.isFile()) {
				throw new Exception("Somente arquivos podem ser enviados.");
			}
			fname = fName;
			fsize = file.length();
		}
		catch ( SocketTimeoutException | ConnectException ste) {
			if ( dst.equals(localUser.getServerID()) ) {
				localUser.removeOfflineUser(dst);
			}
			else {
				OfflineUserMsg of = new OfflineUserMsg( dst, localUser.getServerID());
				of.run();
			}
			cont = false;
		}
		catch (Exception e) {
			e.printStackTrace();
			cont = false;
		}
	}
	
	public void run () {
		
		try {
			if (cont == false) return;
			//copia o arquivo
			File tmp = File.createTempFile(fname, "");
			copyFile(file, tmp);
			
			//Cria o fileInputStream
			fin = new FileInputStream(file);
			

			//Cria o DataOutputStream para avisar o cliente do envio
			out = new ObjectOutputStream(connection.getOutputStream());
			
			//Envia a requisicao
			out.writeUTF( "SENDING_FILE" );
			out.flush();
			out.writeUTF( fname );
			out.flush();
			out.writeLong( fsize );
			out.flush();
			
			//Cria DataInputStream
			in = new ObjectInputStream(connection.getInputStream());
			
			//Espera a resposta
			String ans = "NotOk";
			ans = in.readUTF();
			
			//Verifica se pode ser feito o envio
			if (!ans.equals("OK")) {
				System.out.println( "O usuario nao deseja receber o arquivo " + fname );
				return;
			}
			
			//Comeca a enviar
			System.out.println( fsize );
			System.out.println( (int) fsize );
			byte [] SendFile = new byte [ (int) fsize ];
			fin.read(SendFile);
			
			out.write(SendFile);
			out.flush();
			
		}
		catch ( SocketTimeoutException | ConnectException ste) {
			if ( dst.equals(localUser.getServerID()) ) {
				localUser.removeOfflineUser(dst);
			}
			else {
				OfflineUserMsg of = new OfflineUserMsg( dst, localUser.getServerID());
				of.run();
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			try {
				connection.close();
				out.close();
				in.close();
				fin.close();
			}
			catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}